/* Archive Extractor
 * Copyright 2008-2009 Matthew Hoops
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $URL: http://archive-extractor.googlecode.com/svn/trunk/lab.cpp $
 * $Id: lab.cpp 2 2009-03-23 01:29:43Z clone2727 $
 *
 */

#include "lab.h"

#define BUFSIZE 16384

LabArchive::LabArchive() : StandardArchive() {
}

std::vector<const char*> LabArchive::getArchiveExtensions() {
	std::vector<const char*> exList;
	exList.push_back("lab");
	return exList;
}

int LabArchive::detect(FILE* file) {
	if (readUint32BE(file) == 'LABN')
		return 100;
	return 0;
}

struct LabEntry {
	uint32 stringOffset;
	uint32 offset;
	uint32 size;
};

bool LabArchive::extractFiles(FILE* file) {
	readUint32BE(file); // Skip header
	readUint32LE(file); // Skip unused
	uint32 entryCount = readUint32LE(file);
	uint32 stringTableSize = readUint32LE(file);
	LabEntry *labEntries = new LabEntry[entryCount];
	
	// Read in the string table
	char *stringTable = new char[stringTableSize];
	fseek(file, 16 * (entryCount + 1), SEEK_SET);
	fread(stringTable, 1, stringTableSize, file);
	
	// Read the file entries
	fseek(file, 16, SEEK_SET);
	for (uint32 i = 0; i < entryCount; i++) {
		labEntries[i].stringOffset = readUint32LE(file);
		labEntries[i].offset = readUint32LE(file);
		labEntries[i].size = readUint32LE(file);
		readUint32LE(file); // Skip unused
	}
	
	// Extract the files
	byte *data = (byte *)malloc(BUFSIZE);
	for (uint32 i = 0; i < entryCount; i++) {
		printf ("Extracting file \'%s\'...\n", stringTable + labEntries[i].stringOffset);
		
		FILE *output = fopen(stringTable + labEntries[i].stringOffset, "wb");
		if (!output) {
			printf ("Could not open file for output!\n");
			return false;
		}
		
		fseek(file, labEntries[i].offset, SEEK_SET);
		
		while (labEntries[i].size) {
			uint32 calcSize = BUFSIZE;
			if (labEntries[i].size < BUFSIZE)
				calcSize = labEntries[i].size;
			labEntries[i].size -= calcSize;
			
			fread(data, 1, calcSize, file);
			fwrite(data, 1, calcSize, output);
		}
		
		fflush(output);
		fclose(output);
	}
	
	free(data);
	delete[] labEntries;
	delete[] stringTable;
	return true;
}
